package com.bamboocloud.im.simpleConnector.simpleConnector.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
import org.identityconnectors.framework.common.exceptions.InvalidAttributeValueException;
import org.identityconnectors.framework.common.objects.*;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

public class HttpUtil {
    private static final Log logger = null;

    private static PoolingHttpClientConnectionManager connectionManager;

    private static RequestConfig requestConfig;

    private static final int MAX_TIMEOUT = 10000;

    //初始化连接参数
    static{
        //设置连接池
        connectionManager = new PoolingHttpClientConnectionManager();
        //设置连接池大小
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(connectionManager.getMaxTotal());
        connectionManager.setValidateAfterInactivity(1000);
        RequestConfig.Builder configBuilder = RequestConfig.custom();
        //设置连接超时
        configBuilder.setConnectTimeout(MAX_TIMEOUT);
        //设置读取超时
        configBuilder.setSocketTimeout(MAX_TIMEOUT);
        //设置从连接池获取连接实例的超时
        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
        //设置在提交请求之前，测试连接是否可用
//        configBuilder.setStaleConnectionCheckEnabled(true);
        requestConfig = configBuilder.build();
    }

    /**
     * 发送get请求(Http), 不带数据
     * @param url
     * @return
     */
    public static String doGet(String url){
        return doGet(url, new HashMap<String, Object>());
    }

    /**
     * 发送get请求（Http），带数据，K-V形式
     * @param url
     * @param params
     * @return
     */
    public static String doGet(String url, Map<String, Object> params){
        String apiUrl = url;
        StringBuffer param = new StringBuffer();
        int i = 0;
        //将参数拼接成get请求的url地址参数，例如：http://baidu.com?userId=1&username=name
        //keySet方法获取map里面所有的key值,返回一个集合
        for(String key : params.keySet()){
            if(i == 0){
                param.append("?");
            }else {
                param.append("&");
            }
            param.append(key).append("=").append(params.get(key));
            i++;
        }
        apiUrl += param;
        String result = null;
        HttpClient httpClient = null;
        //判断是http还是https请求
        if(apiUrl.startsWith("https")){
            //https请求客户端
            httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
                    .setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();
        }else {
            //http请求客户端
            httpClient = HttpClients.createDefault();
        }
        HttpGet httpGet = new HttpGet(apiUrl);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity httpEntity = response.getEntity();
            if(httpEntity != null){
                //以流的方式获取http报文实体内容
                InputStream inputStream = httpEntity.getContent();
                result = IOUtils.toString(inputStream, "UTF-8");
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 发送Post请求（Http），不带输入数据
     * @param apiUrl
     * @return
     */
    public static String doPost(String apiUrl){
        return doPost(apiUrl, new HashMap<String, Object>());
    }


    /**
     * 发送Post请求，带输入数据，K-V形式
     * @param apiUrl
     * @param params
     * @return
     */
    public static String doPost(String apiUrl, Map<String, Object> params){
        CloseableHttpClient httpClient = null;
        //如果是https请求
        if(apiUrl.startsWith("https")){
            httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
                    .setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();
        }else {
            //如果是http请求
            httpClient = HttpClients.createDefault();
        }
        String httpStr = null;
        //创建Post方法请求实例
        HttpPost httpPost = new HttpPost(apiUrl);
        //创建响应实例
        CloseableHttpResponse response = null;
        try {
            //设置请求参数
            httpPost.setConfig(requestConfig);
            //创建一个请求参数数据集合,entrySet返回Map.entry类型的set集合
            List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size());
            for(Map.Entry<String, Object> entry : params.entrySet()){
                //封装成K-V的NameValuePair类型的list对象
                NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getKey());
                pairList.add(pair);
            }
            //填充请求参数数据
            httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8")));
            response = httpClient.execute(httpPost);
            //获取响应消息实体
            HttpEntity httpEntity = response.getEntity();
            //响应消息实体转String
            httpStr = EntityUtils.toString(httpEntity);
        } catch (IOException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }finally {
            if(response != null){
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    logger.error(e.getMessage());
                    e.printStackTrace();
                }
            }
            //返回响应消息
            return httpStr;
        }
    }

    /**
     * 发送post请求，带参数数据，JSON形式
     * @param apiUrl
     * @param json
     * @return
     */
    public static String doPost(String apiUrl, Object json){
        CloseableHttpClient httpClient = null;
        if(apiUrl.startsWith("https")){
            httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
                    .setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();
        }else{
            httpClient = HttpClients.createDefault();
        }
        String httpStr = null;
        //创建请求实例
        HttpPost httpPost = new HttpPost(apiUrl);
        //请求发送后返回的响应消息对象
        CloseableHttpResponse response = null;
        try {
            //设置请求参数
            httpPost.setConfig(requestConfig);
            //解决中文乱码问题,填充请求参数数据
            StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");
            stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            //发送请求
            response = httpClient.execute(httpPost);
            //获取响应消息实体
            HttpEntity httpEntity = response.getEntity();
            httpStr = EntityUtils.toString(httpEntity, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(response != null){
                //关闭httpEntity流
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return httpStr;
    }

    //建立SSL安全连接
    private static SSLConnectionSocketFactory createSSLConnSocketFactory(){
        SSLConnectionSocketFactory sslf = null;
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustAllStrategy(){
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException{
                    return true;
                }
            }).build();
            sslf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return false;
                }
            });
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return sslf;
    }

    //构建请求参数
    public static String getAppRequestParams(final Set<Attribute> createAttributes, final Map<String, String> bimRequestParams){

        final JSONObject requestJson = new JSONObject();
        //填充bim请求参数
        for(final String key : bimRequestParams.keySet()){
            requestJson.put(key, bimRequestParams.get(key));
        }
        // do real create here
        if(createAttributes != null){
            for(org.identityconnectors.framework.common.objects.Attribute attribute : createAttributes){
                //打印属性对象信息
                System.out.println("Attribute：" + attribute);
                final String attributeName = attribute.getName();
                //填充一般属性，过滤__PASSWORD__和以“__”开头的属性
                if(attribute.getName() != null && !attributeName.startsWith("__") && !attributeName.equals("__PASSWORD__")){
                    requestJson.put(attributeName, attribute.getValue().get(0));
                }else {
                    //对密码进行明文加密
                    if(!"__PASSWORD__".equals(attributeName) || attribute.getValue() == null){
                        continue;
                    }
                    final String [] pwd = {null};
                    final GuardedString guardedString = AttributeUtil.getGuardedStringValue(attribute);
                    guardedString.access(new GuardedString.Accessor(){
                        @Override
                        public void access(char[] clearChars) {
                            pwd[0] = new String(clearChars);
                        }
                    });
                    requestJson.put("password", pwd[0]);
                }
            }
        }
        return requestJson.toJSONString();
    }

    public static Map<String, String> getBimRequestParams(final String bimRemoteUser, final GuardedString guardedString){
        final Map<String, String> bimRequestParams = new HashMap<String, String>();
        final String bimRequestId = UUID.randomUUID().toString();
        final String [] bimRemotePwd = {null};
        guardedString.access(new GuardedString.Accessor() {
            @Override
            public void access(char[] clearChars) {
                bimRemotePwd[0] = new String(clearChars);
            }
        });
        bimRequestParams.put("bimRequestId", bimRequestId);
        bimRequestParams.put("bimRemoteUser", bimRemoteUser);
        try{
            bimRequestParams.put("bimRemotePwd", AESOperator.encrypt(bimRemotePwd[0]));
        }catch (Exception e){
            e.printStackTrace();
        }
        return bimRequestParams;
    }
}
